package com.taplinker.client.core.image;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Log;
import android.view.View.OnClickListener;
import android.widget.ImageView;

import com.taplinker.client.AppConfigContext;
import com.taplinker.client.core.LocalFileManager;
import com.taplinker.client.widget.image.IImageLoader;
import com.taplinker.client.widget.image.ImageOptions;
import com.taplinker.core.cache.CacheOutException;
import com.taplinker.core.cache.MemCacheImpl;
import com.taplinker.core.rpc.Result;
import com.taplinker.core.rpc.command.SimpleBaseCommand;
import com.taplinker.core.rpc.http.HttpTemplate;
import com.taplinker.core.rpc.http.client.cache.CacheKey;
import com.taplinker.core.rpc.http.client.cache.HttpCacheDAO;
import com.taplinker.core.rpc.http.client.cache.HttpCacheItem;
import com.taplinker.core.util.ImageUtil;
import com.taplinker.core.util.LogUtil;

public class ImageManager {
	private MemCacheImpl memCache;
	private HashMap<String, LinkedList<UrlImageView>> imgDownloadMap = new HashMap<String, LinkedList<UrlImageView>>();
	private static ImageManager instance;
	
	private ImageManager() {
	}
	
	public static ImageManager getInstance() {
		if(instance != null) {
			return instance;
		}
		synchronized (ImageManager.class) {
			if (instance == null) {
				instance = new ImageManager();
			}
		}
		return instance;
	}
	
	public void initialize(Context context) {
		memCache = new MemCacheImpl(context);
		memCache.mallocSpace();
	}
	
	
	public ImageMaxMinUrl loadImg(String url, final IImageLoader ivLoader, OnClickListener onClickListener) {
		if (TextUtils.isEmpty(url)) return null;
		ImageMaxMinUrl urls = null;
		String path = "";
		String cachekey = CacheKey.getCacheKey(url);
		Bitmap bitmap;
		if(onClickListener != null) {
			ivLoader.setClickListener(onClickListener);
		}
		if (memCache != null && (bitmap = memCache.readCache(cachekey)) != null) {
            ivLoader.loadComplete(bitmap);
        } else {
			// 是本地用户应用文件夹图片
			if(url.contains(LocalFileManager.getInstance().getAppUserRootDir())) {
				try {
					ivLoader.loadComplete(ImageUtil.getLocalImage(url));
				} catch (FileNotFoundException e) {
					ivLoader.loadError(0);
					e.printStackTrace();
				}
			// 网络图片
			} else if (url.contains("http://")) {
				downloadImg(url, ivLoader, new ImageManager.CallBack() {
					
					@Override
					public void success(ImageMaxMinUrl urls) {
						if(urls == null) {
							return;
						}
						try{
							if(ivLoader.isShowMaxImage()) {
								ivLoader.loadComplete(ImageUtil.getLocalImage(urls.maxUrl));
							} else {
								ivLoader.loadComplete(ImageUtil.getLocalImage(urls.minUrl));
							}
						} catch (Exception e) {
							ivLoader.loadError(0);
						}
					}
					
					@Override
					public void failure(String message) {
						ivLoader.loadError(0);
					}
					
					@Override
					public void alwaysDo() {
						
					}
				});
			// 本地其他图片
			} else {
				try {
					Bitmap bt;
					urls = createMaxMinImage(url);
					if(ivLoader.isShowMaxImage()) {
						path = urls.maxUrl;
					} else {
						path = urls.minUrl;
					}
					bt = ImageUtil.getLocalImage(path);
					ivLoader.loadComplete(bt);
				} catch (FileNotFoundException e) {
					ivLoader.loadError(0);
					e.printStackTrace();
				}
			}
		}
		return urls;
        
	}
	
	/**
	 * 生成大小图
	 * @param path
	 * @return
	 */
	public ImageMaxMinUrl createMaxMinImage(String path) {
		String maxPath = LocalFileManager.getInstance().getImageDir() + "/" + ImageUtil.getNameFromPath(path);
		File maxFile = new File(maxPath);
		if(!maxFile.exists()) {
			maxPath = getCompressImage(path, new ImageOptions(true));
		}
		String minPath = LocalFileManager.getInstance().getImage2Dir() + "/" + ImageUtil.getNameFromPath(path);
		File minFile = new File(minPath);
		if(!minFile.exists()) {
			minPath = getCompressImage(path, new ImageOptions(false));
		}
		return new ImageMaxMinUrl(maxPath, minPath);
	}
	
	/**
	 * 根据大图路径返回小图路径
	 * @param path
	 * @return
	 */
	public String findMinImageByMax(String path) {
		return path.replace(LocalFileManager.getInstance().getImageDir(), LocalFileManager.getInstance().getImage2Dir());
	}
	
	/**
	 * 根据小图路径返回大图路径
	 * @param path
	 * @return
	 */
	public String findMaxImageByMin(String path) {
		return path.replace(LocalFileManager.getInstance().getImage2Dir(), LocalFileManager.getInstance().getImageDir());
	}
	
	public String getCompressImage(String path, ImageOptions imgOpts){
		if(TextUtils.isEmpty(path)) {
			return null;
		}
		final String targetDir;
		if(imgOpts.isMax()){
			targetDir = LocalFileManager.getInstance().getImageDir();
		} else {
			targetDir = LocalFileManager.getInstance().getImage2Dir();
		}
		try {
			return ImageUtil.getCompressImage(path, imgOpts.getWidth(), imgOpts.getHeight(), imgOpts.getMaxKb(), imgOpts.getQuality(), targetDir);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Bitmap getCompressBitmap(String path, ImageOptions imgOpts){
		Bitmap bt;
		try {
			bt = ImageUtil.getLocalImage(getCompressImage(path, imgOpts));
		} catch (FileNotFoundException e) {
			bt = null;
			e.printStackTrace();
		}
		return bt;
	}

	public void downloadImg(String url, IImageLoader ivLoader, CallBack callBack) {
		String cachekey = CacheKey.getCacheKey(url);
		Bitmap bitmap;
		if (memCache != null && (bitmap = memCache.readCache(cachekey)) != null) {
            ivLoader.loadComplete(bitmap);
            if(callBack != null) {
            	callBack.success(null);
            }
        } else {
        	new ImageDownloadCommand(url, ivLoader).execute();
        }
	}
	
   	class ImageDownloadCommand extends SimpleBaseCommand {
    	private String url;
    	private IImageLoader ivLoader;
    	public ImageDownloadCommand(String url, IImageLoader ivLoader) {
    		this.ivLoader = ivLoader;
    		this.ivLoader.loadStart(0);
    		this.url = url;
    		LinkedList<UrlImageView> list = imgDownloadMap.get(url);
    		if(list == null) {
    			list = new LinkedList<ImageManager.UrlImageView>();
    		}
    		if(!list.contains(ivLoader)) {
    			list.addLast(new UrlImageView(ivLoader));
    		}
    	}
    	
    	@Override
    	public Result go() {
    		Result result = new Result();
    		String requestUrl  = url;
    		try  {
    			LogUtil.d("http", url);
    			if(url.contains("http://")) {
    				HttpCacheItem item = HttpCacheDAO.getInstance().getFileIndexItem(CacheKey.getCacheKey(new URL(requestUrl).getPath()));
    				if(item != null && !item.isTemp() && new File(item.getPath()).exists()) {
        				requestUrl = item.getPath();
    				} else {
        				requestUrl = new HttpTemplate().download(url, this).object.toString();	
        			}
    			}
    			LogUtil.d("http", requestUrl);
				result.object = requestUrl;
    		} catch(Exception e) {
    			e.printStackTrace();
    		} 
			return result;
    	}

    	@Override
		protected void update(long planSize, long curSize) {
    		ivLoader.updateProgress(planSize, curSize);
		}

		@Override
    	public void yes(Result result) {
			try {
				ImageOptions imOpts = new ImageOptions();
				imOpts.setMax(ivLoader.isShowMaxImage());
				Bitmap bt = getCompressBitmap((String) result.object, imOpts);
				ivLoader.loadComplete(bt); 
				LogUtil.d("http", "图片展示完成");
				if(bt != null) {
					memCache.writeCache(CacheKey.getCacheKey((String) result.object), bt);
				} else {
					ivLoader.loadError(0);
				}
			} catch (CacheOutException e) {
				e.printStackTrace();
				Log.d("tag", result.message);
			}
    	}
    	
    	@Override
    	public void no(Result result) {
    		super.no(result);
    		imgDownloadMap.remove(url);
    		ivLoader.loadError(0);
			Log.d("tag", "下载失败");
    	}
    	
    }
	
	public void uploadImg(File file, IImageLoader ivLoader, Context context) {
		new UploadCommand(file, ivLoader, context).execute();
	}
	
	class UploadCommand extends SimpleBaseCommand{
    	private File file;
    	private IImageLoader ivLoader;
    	public UploadCommand(File file, IImageLoader ivLoader, Context context) {
    		super(context);
    		this.file = file;
    		this.ivLoader = ivLoader;
    	}
    	
    	public UploadCommand(String path, IImageLoader ivLoader, Context context) {
    		this(new File(path), ivLoader, context);
    	}
    	
    	@Override
    	public Result go() {
    		if(ivLoader != null) {
    			try {
    				ivLoader.loadComplete(ImageUtil.getLocalImage(file.getPath()));
    			} catch (FileNotFoundException e) {
    				ivLoader.loadError(0);
    				e.printStackTrace();
    			}
    		}
    		return new HttpTemplate().upload(AppConfigContext.TAPLINKER_WEB
    				+ "/services/v2/upload"
    				, file ,this);
    	}

    	@Override
    	public void yes(Result result) {
			try {
				URL url = new URL(AppConfigContext.WEB_DISK_ROOT + result.object.toString());
				HttpCacheDAO.getInstance().insert(CacheKey.getCacheKey(url.getPath()), file.getPath(), 1, "false");
			} catch (MalformedURLException e) {
				if(ivLoader != null) {
					ivLoader.loadError(0);
				}
				e.printStackTrace();
			}
    	}

    	@Override
    	public void no(Result result) {
    		super.no(result);
    		if(ivLoader != null) {
    			ivLoader.loadError(0);
    		}
    	}
    	
    	@Override
    	protected void update(long planSize, long curSize) {
    		if(ivLoader != null) {
    			ivLoader.updateProgress(planSize, curSize);
    		}
    	}
    	
    }
	
	class UrlImageView {
		private WeakReference<IImageLoader> imgView;
		public UrlImageView(IImageLoader imageView) {
			imgView = new WeakReference<IImageLoader>(imageView);
		}
	}

	public void remove(ImageView imageView) {
		Iterator<Entry<String, LinkedList<UrlImageView>>> iter = imgDownloadMap.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<String, LinkedList<UrlImageView>> entity = iter.next();
			if (entity.getValue() == null){
				return;
			}
			Iterator<UrlImageView> listIterator = entity.getValue().iterator();
			while (listIterator.hasNext()) {
				if (listIterator.next().imgView.get() == imageView) {
					LogUtil.d("http", "imageview is replaced ");
					listIterator.remove();
				}
			}
		}
	}
	
	public class ImageMaxMinUrl {
		public String maxUrl;
		public String minUrl;
		public ImageMaxMinUrl(String maxUrl, String minUrl) {
			super();
			this.maxUrl = maxUrl;
			this.minUrl = minUrl;
		}
		
		public boolean isEmpty() {
			if(TextUtils.isEmpty(maxUrl) || TextUtils.isEmpty(minUrl)) {
				return true;
			}
			return false;
		}
	}
	
	public interface CallBack {
		public void success(ImageMaxMinUrl urls);
		public void failure(String message);
		public void alwaysDo();
	}
		
}
